package com.by_man.presenter.module_bluetooth;

import android.annotation.TargetApi;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class BluetoothLeService extends Service {
    public static final String ACTION_DATA_AVAILABLE = "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
    public static final String ACTION_DATA_WRITEN = "com.example.bluetooth.le.ACTION_DATA_WRITEN";
    public static final String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
    public static final String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
    public static final String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
    public static final String EXTRA_DATA = "com.example.bluetooth.le.EXTRA_DATA";
    private static final int STATE_CONNECTED = 2;
    private static final int STATE_CONNECTING = 1;
    private static final int STATE_DISCONNECTED = 0;
    private static final String TAG = BluetoothLeService.class.getSimpleName();
    public final UUID UUID_SPPLE_NOTIFY = UUID.fromString(SampleGattAttributes.SPPLE_NOTIFY);
    public final UUID UUID_SPPLE_POUT = UUID.fromString(SampleGattAttributes.SPPLE_POUT);
    public final UUID UUID_SPPLE_SERV = UUID.fromString(SampleGattAttributes.SPPLE_SERV);
    public final UUID UUID_SPPLE_WRITE = UUID.fromString(SampleGattAttributes.SPPLE_WRITE);
    private final IBinder mBinder = new LocalBinder();
    private BluetoothAdapter mBluetoothAdapter;
    private String mBluetoothDeviceAddress;
    private BluetoothGatt mBluetoothGatt;
    private BluetoothManager mBluetoothManager;
    private int mConnectionState = 0;
    private static final int SCREEN_OFF = 0;
    private static final int SCREEN_ON = 1;
    private int screenStatus = SCREEN_ON;
    private byte[] buffer = null;


    // private boolean mConnectionState;
    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback()
    {

        public void onCharacteristicChanged(BluetoothGatt paramAnonymousBluetoothGatt, BluetoothGattCharacteristic paramAnonymousBluetoothGattCharacteristic) {
            Log.i(BluetoothLeService.TAG, "Charas changed.");
            if (screenStatus == SCREEN_OFF) {
                byte[] bytes = paramAnonymousBluetoothGattCharacteristic.getValue();
                Log.e(TAG, Arrays.toString(bytes));
                int pos = -1;
                for(int i = 0; bytes.length > 12 && i < bytes.length - 3; i++) {
                    if (bytes[i] == -128) {
                        pos = i;
                        break;
                    }
                }
                if (pos != -1) {
                    buffer = bytes;
                    Log.e(TAG, "lastCharacteristic: " + Arrays.toString(bytes));
                }
            } else if (screenStatus == SCREEN_ON) {
                BluetoothLeService.this.broadcastUpdate("com.example.bluetooth.le.ACTION_DATA_AVAILABLE", paramAnonymousBluetoothGattCharacteristic);
            }

        }
        public void onCharacteristicWrite(BluetoothGatt paramAnonymousBluetoothGatt, BluetoothGattCharacteristic paramAnonymousBluetoothGattCharacteristic, int paramAnonymousInt) {
            if (paramAnonymousInt == 0) {
                BluetoothLeService.this.broadcastUpdate("com.example.bluetooth.le.ACTION_DATA_WRITEN", paramAnonymousBluetoothGattCharacteristic);
                Log.i(BluetoothLeService.TAG, "Charas write OK.");
            } else {

                Log.w(BluetoothLeService.TAG, "Charas write FAIL.");

            }
        }
        public void onConnectionStateChange(BluetoothGatt paramAnonymousBluetoothGatt, int paramAnonymousInt1, int paramAnonymousInt2) {
            if (paramAnonymousInt2 == 2) {
                BluetoothLeService.this.mConnectionState = 2;
                BluetoothLeService.this.broadcastUpdate("com.example.bluetooth.le.ACTION_GATT_CONNECTEDACTION_GATT_CONNECTED");
                Log.i(BluetoothLeService.TAG, "GATT server connected, Service discovery started = " + BluetoothLeService.this.mBluetoothGatt.discoverServices());
            } else {

                if (paramAnonymousInt2 == 0) {
                    BluetoothLeService.this.mConnectionState = 0;
                    BluetoothLeService.this.broadcastUpdate("com.example.bluetooth.le.ACTION_GATT_DISCONNECTED");
                    Log.i(BluetoothLeService.TAG, "GATT server disconnected.");
                } else {
                    Log.i(BluetoothLeService.TAG, "onConnectionStateChange: unknow new State.");
                }

            }
        }
        public void onServicesDiscovered(BluetoothGatt paramAnonymousBluetoothGatt, int paramAnonymousInt) {
            if (paramAnonymousInt == 0) {
                BluetoothLeService.this.broadcastUpdate("com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED");
                Log.i(BluetoothLeService.TAG, "GATT service found.");
            } else {
                Log.w(BluetoothLeService.TAG, "onServicesDiscovered received: " + paramAnonymousInt);
            }
        }
    };

    public void broadcastUpdate(String paramString) {
        sendBroadcast(new Intent(paramString));
    }

    private void broadcastUpdate(String paramString, BluetoothGattCharacteristic paramBluetoothGattCharacteristic) {
        Intent localIntent = new Intent(paramString);
        if (this.UUID_SPPLE_NOTIFY.equals(paramBluetoothGattCharacteristic.getUuid())) {
            byte[] arrayOfByte = paramBluetoothGattCharacteristic.getValue();
            if ((arrayOfByte != null) && (arrayOfByte.length > 0))
                localIntent.putExtra("com.example.bluetooth.le.EXTRA_DATA", arrayOfByte);
        }
        sendBroadcast(localIntent);
    }

    public void close() {
        if (this.mBluetoothGatt == null) ;
        else {

            this.mBluetoothGatt.close();
            this.mBluetoothGatt = null;
            Log.e(TAG,"service close");
            return;
        }
    }

    public boolean connect(String paramString) {
        int i;
        if ((this.mBluetoothAdapter == null) || (paramString == null)) {
            Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
            i = 0;
        } else {

            if ((this.mBluetoothDeviceAddress != null) && (paramString.equals(this.mBluetoothDeviceAddress)) && (this.mBluetoothGatt != null)) {
                if (this.mBluetoothGatt.connect()) {
                    this.mConnectionState = 0;
                    Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection...OK");
                } else {
                    Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection...FAIL");
                    i =0;
                }
            } else {
                BluetoothDevice localBluetoothDevice = this.mBluetoothAdapter.getRemoteDevice(paramString);
                if (localBluetoothDevice == null) {
                    Log.w(TAG, "Device not found.  Unable to connect.");
                    i = 0;
                } else {
                    this.mBluetoothGatt = localBluetoothDevice.connectGatt(this, false, this.mGattCallback);
                    Log.d(TAG, "Trying to create a new connection.");
                    this.mBluetoothDeviceAddress = paramString;
                    this.mConnectionState = 1;
                }
            }
        }
       return true;
    }

    public void disconnect() {
        if ((this.mBluetoothAdapter == null) || (this.mBluetoothGatt == null))
            Log.w(TAG, "BluetoothAdapter not initialized");
        else {

            this.mBluetoothGatt.disconnect();

        }
    }

    public List<BluetoothGattService> getSupportedGattServices()
    {
        if (this.mBluetoothGatt == null)
            return null;
        List<BluetoothGattService> listBluetoothGattService = new ArrayList<>();
        for (BluetoothGattService localObject :this.mBluetoothGatt.getServices())
            listBluetoothGattService.add(localObject);
        return listBluetoothGattService;
    }

    public boolean initialize( ) {
        boolean bool;
        if (this.mBluetoothManager == null) {
            this.mBluetoothManager = ((BluetoothManager) getSystemService(BLUETOOTH_SERVICE));
            if (this.mBluetoothManager == null) {
                Log.e(TAG, "Unable to initialize BluetoothManager.");
                bool = false;
            } else {

                this.mBluetoothAdapter = this.mBluetoothManager.getAdapter();
                if (this.mBluetoothAdapter == null) {
                    Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
                    bool = false;
                } else {
                    Log.e(TAG, "Succeed to obtain a BluetoothAdapter.");
                    bool = true;

                }
            }
        }
        return true;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

    }
    @Override
    public void onStart(Intent intent, int startId) {
        Log.e(TAG, "start onStart~~~");
        super.onStart(intent, startId);
    }



    @Override
    public void onCreate() {
        super.onCreate();

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        filter.addAction(Intent.ACTION_SCREEN_ON);

        BroadcastReceiver screenOffOn = new BroadcastReceiver() {
            @Override
            public void onReceive(final Context context, final Intent intent) {
                String action = intent.getAction();
                if (Intent.ACTION_SCREEN_ON.equals(action)) {
                    screenStatus = SCREEN_ON;
                    if (buffer != null) {
                        Intent lastIntent = new Intent("com.example.bluetooth.le.ACTION_DATA_AVAILABLE");
                        lastIntent.putExtra("com.example.bluetooth.le.EXTRA_DATA", buffer);
                        sendBroadcast(lastIntent);
                    }
                } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                    Log.e(TAG, "SCREEN_OFF");
                    screenStatus = SCREEN_OFF;
                }
            }
        };
        registerReceiver(screenOffOn, filter);
    }

    public IBinder onBind(Intent paramIntent)
    {
        if (initialize()) {
            connect(paramIntent.getStringExtra("mac_address"));
            Log.i(TAG, "service onbind");
        }
        return this.mBinder;
    }

    public boolean onUnbind(Intent paramIntent)
    {
        Log.i(TAG, "Unbind complete.");
        close();
        return super.onUnbind(paramIntent);
    }

    public void readCharacteristic(BluetoothGattCharacteristic paramBluetoothGattCharacteristic)
    {
        if ((this.mBluetoothAdapter == null) || (this.mBluetoothGatt == null))
            Log.w(TAG, "BluetoothAdapter not initialized");
        else
        {
            this.mBluetoothGatt.readCharacteristic(paramBluetoothGattCharacteristic);
            return;
        }
    }

    public void setCharacteristicNotification(BluetoothGattCharacteristic paramBluetoothGattCharacteristic, boolean paramBoolean)
    {
        if ((this.mBluetoothAdapter == null) || (this.mBluetoothGatt == null))
            Log.w(TAG, "BluetoothAdapter not initialized");
        else
        {

            this.mBluetoothGatt.setCharacteristicNotification(paramBluetoothGattCharacteristic, paramBoolean);
            if (this.UUID_SPPLE_NOTIFY.equals(paramBluetoothGattCharacteristic.getUuid()))
            {
                BluetoothGattDescriptor localBluetoothGattDescriptor = paramBluetoothGattCharacteristic.getDescriptor(UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
                localBluetoothGattDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                this.mBluetoothGatt.writeDescriptor(localBluetoothGattDescriptor);
                return;
            }
        }
    }

    public void writeCharacteristic(BluetoothGattCharacteristic paramBluetoothGattCharacteristic)
    {
        if ((this.mBluetoothAdapter == null) || (this.mBluetoothGatt == null))
            Log.w(TAG, "BluetoothAdapter not initialized");
        else
        {

            this.mBluetoothGatt.writeCharacteristic(paramBluetoothGattCharacteristic);
            return;
        }
    }

    public class LocalBinder extends Binder
    {
        public LocalBinder()
        {
        }

        BluetoothLeService getService()
        {
            return BluetoothLeService.this;
        }
    }
}